<script lang="ts" setup>
import type { FormInstance } from 'ant-design-vue';

import type { RoleInfo } from '#/api/core/role';

import { computed, onMounted, ref, watch } from 'vue';

import { useVbenModal } from '@vben/common-ui';

import { Icon } from '@iconify/vue/dist/iconify.js';
import { Form, Input, message, Radio, Select } from 'ant-design-vue';

import { saveMenuApi } from '#/api/core/menu';
import { getSysRoles } from '#/api/core/role';
import { $t } from '#/locales';
import { getDesignerApi, type DesignerApi } from '#/api/core/designer';

const emit = defineEmits<{
  save: [data: any];
}>();

interface FormState {
  id?: number;
  title: string;
  name: string;
  path: string;
  component: string;
  icon: string;
  code: string;
  description: string;
  redirect: string;
  parentId: number;
  sort: number;
  relationType: 'same' | 'sub';
  menuType: 'function' | 'group' | 'lowcode';
  roles: string;
}

const formRef = ref<FormInstance>();
const formState = ref<FormState>({
  id: 0,
  title: '',
  name: '',
  path: '',
  component: 'BasicLayout',
  icon: '',
  code: '',
  description: '',
  redirect: '',
  parentId: 0,
  sort: 0,
  relationType: 'sub',
  menuType: 'group',
  roles: '',
});

// 监听组件值变化
watch(
  () => formState.value.component,
  (newComponent) => {
    // 只在非低代码菜单时改变menuType
    if (formState.value.menuType !== 'lowcode') {
      formState.value.menuType =
        newComponent === 'BasicLayout' ? 'group' : 'function';
    }
  },
);

// 监听菜单类型变化
watch(
  () => formState.value.menuType,
  (newType) => {
    if (newType === 'group') {
      formState.value.component = 'BasicLayout';
    } else if (newType === 'function') {
      formState.value.component = '';
    } else if (newType === 'lowcode') {
      formState.value.component = '/lowcode/publish/index';
    }
  },
);

async function onSubmit(values: FormState) {
  const menuData = {
    id: values.id,
    title: values.title,
    name: values.name,
    path: values.path,
    component: values.component,
    icon: values.icon,
    code: values.code,
    description: values.description,
    redirect: values.redirect,
    parentId: Number(values.parentId),
    sort: values.sort,
    menuType: values.menuType,
    roles: values.roles,
  };

  await saveMenuApi(menuData);
}

const [Modal, modalApi] = useVbenModal({
  draggable: true,
  async onConfirm() {
    try {
      await formRef.value?.validate();
      const { isEdit, parentId, id } = modalApi.getData<{
        id: number | string;
        isEdit: boolean;
        parentId: number | string;
      }>();

      const saveData: FormState = {
        ...formState.value,
        parentId:
          formState.value.relationType === 'same'
            ? Number(parentId)
            : Number(id),
      };

      if (isEdit) {
        saveData.id = formState.value.id;
        saveData.parentId = formState.value.parentId;
      }

      await onSubmit(saveData);
      emit('save', saveData);
      modalApi.close();
      message.success($t('menu.save.success'));
      return true;
    } catch (error: any) {
      message.error(error.message || $t('menu.save.failed'));
      return false;
    }
  },
  onCancel() {
    formRef.value?.resetFields();
    modalApi.close();
  },
  onOpenChange(isOpen: boolean) {
    if (isOpen) {
      const data = modalApi.getData<{
        editData: any;
        isEdit: boolean;
        parentId: number | string;
      }>();

      formState.value = data.editData
        ? {
            id: Number(data.editData.id),
            title: data.editData.title,
            name: data.editData.name,
            path: data.editData.path,
            component: data.editData.component,
            icon: data.editData.icon,
            code: data.editData.code,
            description: data.editData.description,
            redirect: data.editData.redirect || '',
            parentId: data.isEdit
              ? Number(data.editData.parentId)
              : Number(data.parentId),
            sort: data.editData.sort || 0,
            relationType: 'sub',
            menuType: data.editData.component === '/lowcode/publish/index'
              ? 'lowcode'
              : data.editData.component === 'BasicLayout'
              ? 'group'
              : 'function',
            roles: data.editData.roles || '',
          }
        : {
            title: '',
            name: '',
            path: '',
            component: 'BasicLayout',
            icon: '',
            code: '',
            description: '',
            redirect: '',
            parentId: Number(data.parentId),
            sort: 0,
            relationType: 'sub',
            menuType: 'group',
            roles: '',
          };
    } else {
      formRef.value?.resetFields();
    }
  },
});

const showRelationType = computed(() => {
  const { isEdit, parentId } = modalApi.getData<{
    isEdit: boolean;
    parentId: number | string;
  }>();
  return !isEdit && Number(parentId) !== 1;
});

// 常用的图标集合
const commonIcons = [
  // 导航类
  'mdi:home',
  'mdi:view-dashboard',
  'mdi:menu',
  'mdi:arrow-left',
  'mdi:arrow-right',
  'mdi:arrow-up',
  'mdi:arrow-down',
  'mdi:chevron-left',
  'mdi:chevron-right',
  'mdi:chevron-up',
  'mdi:chevron-down',
  'mdi:dots-horizontal',
  'mdi:dots-vertical',
  'mdi:menu-open',
  'mdi:menu-close',
  'mdi:menu-swap',
  'mdi:page-first',
  'mdi:page-last',
  'mdi:step-backward',
  'mdi:step-forward',
  'mdi:view-list',
  'mdi:view-grid',
  'mdi:view-module',
  'mdi:view-carousel',
  'mdi:view-column',
  'mdi:view-dashboard-variant',

  // 用户与权限
  'mdi:account',
  'mdi:account-group',
  'mdi:account-circle',
  'mdi:account-key',
  'mdi:account-cog',
  'mdi:account-details',
  'mdi:security',
  'mdi:shield',
  'mdi:shield-check',
  'mdi:shield-alert',
  'mdi:lock',
  'mdi:lock-open',
  'mdi:key',
  'mdi:key-variant',
  'mdi:account-supervisor',
  'mdi:account-multiple',
  'mdi:account-convert',
  'mdi:account-edit',
  'mdi:account-group-outline',
  'mdi:account-star',
  'mdi:account-box',
  'mdi:account-network',
  'mdi:account-settings',
  'mdi:account-search',

  // 数据与分析
  'mdi:chart-bar',
  'mdi:chart-line',
  'mdi:chart-pie',
  'mdi:chart-areaspline',
  'mdi:chart-timeline',
  'mdi:chart-box',
  'mdi:database',
  'mdi:table',
  'mdi:table-large',
  'mdi:table-edit',
  'mdi:table-search',
  'mdi:table-plus',
  'mdi:chart-scatter-plot',
  'mdi:chart-bubble',
  'mdi:chart-donut',
  'mdi:chart-gantt',
  'mdi:chart-histogram',
  'mdi:chart-bell-curve',
  'mdi:chart-box-plus-outline',
  'mdi:database-check',
  'mdi:database-export',
  'mdi:database-import',

  // 文件与文档
  'mdi:file',
  'mdi:file-document',
  'mdi:file-excel',
  'mdi:file-pdf',
  'mdi:file-word',
  'mdi:file-image',
  'mdi:folder',
  'mdi:folder-open',
  'mdi:folder-plus',
  'mdi:folder-download',
  'mdi:folder-upload',
  'mdi:archive',
  'mdi:file-video',
  'mdi:file-music',
  'mdi:file-code',
  'mdi:file-cloud',
  'mdi:file-certificate',
  'mdi:file-chart',
  'mdi:file-cog',
  'mdi:file-export',
  'mdi:file-import',
  'mdi:file-key',
  'mdi:file-lock',
  'mdi:file-multiple',

  // 通信与消息
  'mdi:email',
  'mdi:email-open',
  'mdi:email-send',
  'mdi:message',
  'mdi:message-text',
  'mdi:message-reply',
  'mdi:bell',
  'mdi:bell-ring',
  'mdi:bell-off',
  'mdi:chat',
  'mdi:chat-processing',
  'mdi:comment',
  'mdi:forum',
  'mdi:message-alert',
  'mdi:message-settings',
  'mdi:message-image',
  'mdi:message-video',
  'mdi:message-lock',
  'mdi:message-bookmark',
  'mdi:message-bulleted',
  'mdi:message-cog',
  'mdi:message-flash',

  // 设置与工具
  'mdi:cog',
  'mdi:cogs',
  'mdi:wrench',
  'mdi:tools',
  'mdi:hammer',
  'mdi:screwdriver',
  'mdi:settings',
  'mdi:tune',
  'mdi:filter',
  'mdi:filter-variant',
  'mdi:magnify',
  'mdi:magnify-plus',
  'mdi:toolbox',
  'mdi:ruler',
  'mdi:scissors',
  'mdi:palette',
  'mdi:brush',
  'mdi:format-paint',
  'mdi:calculator',
  'mdi:calculator-variant',
  'mdi:math-compass',
  'mdi:scale-balance',

  // 状态与操作
  'mdi:check',
  'mdi:check-circle',
  'mdi:close',
  'mdi:close-circle',
  'mdi:plus',
  'mdi:plus-circle',
  'mdi:minus',
  'mdi:minus-circle',
  'mdi:alert',
  'mdi:alert-circle',
  'mdi:information',
  'mdi:help-circle',
  'mdi:check-decagram',
  'mdi:close-octagon',
  'mdi:alert-octagon',
  'mdi:alert-decagram',
  'mdi:progress-check',
  'mdi:progress-close',
  'mdi:progress-alert',
  'mdi:progress-clock',

  // 编辑与操作
  'mdi:pencil',
  'mdi:pencil-box',
  'mdi:delete',
  'mdi:delete-forever',
  'mdi:content-copy',
  'mdi:content-paste',
  'mdi:refresh',
  'mdi:sync',
  'mdi:undo',
  'mdi:redo',
  'mdi:format-list-bulleted',
  'mdi:format-list-numbered',
  'mdi:clipboard',
  'mdi:clipboard-check',
  'mdi:clipboard-text',
  'mdi:clipboard-plus',
  'mdi:clipboard-arrow-down',
  'mdi:text-box',
  'mdi:text-box-plus',
  'mdi:text-box-edit',
  'mdi:text-box-search',
  'mdi:text-box-check',

  // 设备与技术
  'mdi:monitor',
  'mdi:laptop',
  'mdi:tablet',
  'mdi:cellphone',
  'mdi:printer',
  'mdi:camera',
  'mdi:server',
  'mdi:server-network',
  'mdi:cloud',
  'mdi:cloud-upload',
  'mdi:cloud-download',
  'mdi:web',
  'mdi:desktop-classic',
  'mdi:desktop-tower',
  'mdi:keyboard',
  'mdi:mouse',
  'mdi:router',
  'mdi:access-point',
  'mdi:usb',
  'mdi:bluetooth',
  'mdi:wifi',
  'mdi:lan',
  'mdi:ip-network',
  'mdi:remote-desktop',

  // 时间与日期
  'mdi:calendar',
  'mdi:calendar-month',
  'mdi:calendar-today',
  'mdi:clock',
  'mdi:clock-outline',
  'mdi:timer',
  'mdi:history',
  'mdi:update',
  'mdi:calendar-check',
  'mdi:calendar-plus',
  'mdi:calendar-edit',
  'mdi:alarm',
  'mdi:calendar-clock',
  'mdi:calendar-range',
  'mdi:calendar-remove',
  'mdi:calendar-sync',
  'mdi:calendar-text',
  'mdi:calendar-search',
  'mdi:calendar-star',
  'mdi:calendar-week',
  'mdi:calendar-weekend',
  'mdi:calendar-blank',

  // 媒体控制
  'mdi:play',
  'mdi:pause',
  'mdi:stop',
  'mdi:skip-previous',
  'mdi:skip-next',
  'mdi:fast-forward',
  'mdi:rewind',
  'mdi:volume-high',
  'mdi:volume-medium',
  'mdi:volume-low',
  'mdi:volume-off',
  'mdi:volume-mute',
  'mdi:playlist-music',
  'mdi:playlist-plus',
  'mdi:playlist-check',
  'mdi:playlist-edit',
  'mdi:music',
  'mdi:music-note',
  'mdi:music-off',
  'mdi:radio',
  'mdi:microphone',
  'mdi:headphones',

  // 其他常用
  'mdi:star',
  'mdi:heart',
  'mdi:thumb-up',
  'mdi:bookmark',
  'mdi:link',
  'mdi:eye',
  'mdi:map-marker',
  'mdi:tag',
  'mdi:currency-usd',
  'mdi:cart',
  'mdi:gift',
  'mdi:certificate',
  'mdi:trophy',
  'mdi:medal',
  'mdi:crown',
  'mdi:flag',
  'mdi:target',
  'mdi:compass',
  'mdi:puzzle',
  'mdi:lightbulb',
  'mdi:rocket',
  'mdi:fire',
  'mdi:weather-sunny',
  'mdi:umbrella',
];

// 修改角色选项的数据结构
interface RoleOption {
  label: string;
  value: number | string;
}

// 角色选项列表
const roleOptions = ref<RoleOption[]>([]);

// 获取系统角色列表
async function loadRoleOptions() {
  try {
    const response = await getSysRoles();
    if (response?.items && Array.isArray(response.items)) {
      roleOptions.value = response.items.map((role: RoleInfo) => ({
        label: role.name,
        value: role.id,
      }));
    } else {
      roleOptions.value = [];
      message.error($t('menu.roles.loadFailed'));
    }
  } catch (error) {
    console.error('Failed to load roles:', error);
    message.error($t('menu.roles.loadFailed'));
  }
}

// 添加设计器选项状态
const designerOptions = ref<{ label: string; value: string }[]>([]);

// 添加加载设计器列表函数
async function loadDesignerOptions() {
  try {
    const { items } = await getDesignerApi({
      page: 1,
      pageSize: 1000
    });
    designerOptions.value = items.map((item: DesignerApi.DesignerModel) => ({
      label: item.name,
      value: item.redirect
    }));
  } catch (error) {
    console.error('加载设计器列表失败:', error);
    message.error('加载设计器列表失败');
  }
}

// 在组件挂载时加载角色列表和设计器列表
onMounted(() => {
  loadRoleOptions();
  loadDesignerOptions();
});
</script>

<template>
  <Modal>
    <Form
      ref="formRef"
      :label-col="{ span: 6 }"
      :model="formState"
      :wrapper-col="{ span: 18 }"
      layout="horizontal"
    >
      <Form.Item
        :label="$t('menu.form.title.label')"
        :rules="[{ required: true, message: $t('menu.form.title.required') }]"
        name="title"
      >
        <Input
          v-model:value="formState.title"
          :placeholder="$t('menu.form.title.placeholder')"
        />
      </Form.Item>

      <Form.Item
        :label="$t('menu.form.name.label')"
        :rules="[{ required: true, message: $t('menu.form.name.required') }]"
        name="name"
      >
        <Input
          v-model:value="formState.name"
          :placeholder="$t('menu.form.name.placeholder')"
        />
      </Form.Item>

      <Form.Item
        :label="$t('menu.form.path.label')"
        :rules="[
          { required: true, message: $t('menu.form.path.required') },
          { pattern: /^\//, message: $t('menu.form.path.format') },
        ]"
        name="path"
      >
        <Input
          v-model:value="formState.path"
          :placeholder="$t('menu.form.path.placeholder')"
        />
      </Form.Item>

      <Form.Item
        :label="$t('menu.form.type.label')"
        :rules="[{ required: true, message: $t('menu.form.type.required') }]"
        name="menuType"
      >
        <Radio.Group v-model:value="formState.menuType">
          <Radio value="group">{{ $t('menu.form.type.group') }}</Radio>
          <Radio value="function">{{ $t('menu.form.type.function') }}</Radio>
          <Radio value="lowcode">{{ $t('menu.form.type.lowcode') }}</Radio>
        </Radio.Group>
      </Form.Item>

      <Form.Item
        :label="$t('menu.form.component.label')"
        :rules="[
          { required: true, message: $t('menu.form.component.required') },
          {
            pattern:
              formState.menuType === 'function' ? /^(\/[\w-]+)+$/ : undefined,
            message: $t('menu.form.component.format'),
          },
        ]"
        name="component"
        v-if="formState.menuType !== 'lowcode'"
      >
        <Input
          v-model:value="formState.component"
          :disabled="formState.menuType === 'group'"
          :placeholder="$t('menu.form.component.placeholder')"
        />
      </Form.Item>
      <Form.Item
        :label="$t('menu.form.component.label')"
        :rules="[
          { required: true, message: $t('menu.form.component.required') },
        ]"
        name="component"
        v-if="formState.menuType === 'lowcode'"
      >
        <Select
          v-model:value="formState.redirect"
          :options="designerOptions"
          :placeholder="$t('menu.form.path.select')"
        />
      </Form.Item>
      <Form.Item
        :label="$t('menu.form.icon.label')"
        :rules="[{ required: true, message: $t('menu.form.icon.required') }]"
        name="icon"
      >
        <Select
          v-model:value="formState.icon"
          :allow-clear="false"
          :dropdown-style="{ padding: '4px' }"
          :filter-option="false"
          :placeholder="$t('menu.form.icon.placeholder')"
          :show-arrow="true"
          :show-search="false"
        >
          <template #suffixIcon>
            <Icon
              v-if="formState.icon"
              :icon="formState.icon"
              class="text-lg"
            />
          </template>
          <template #dropdownRender>
            <div class="icon-dropdown">
              <div class="icon-grid">
                <div
                  v-for="icon in commonIcons"
                  :key="icon"
                  :class="{ 'bg-primary-100': formState.icon === icon }"
                  class="icon-item flex cursor-pointer items-center justify-center rounded p-3 hover:bg-gray-100"
                  @click="formState.icon = icon"
                >
                  <Icon :icon="icon" class="text-2xl" />
                </div>
              </div>
            </div>
          </template>
        </Select>
      </Form.Item>

      <Form.Item
        :label="$t('menu.form.code.label')"
        :rules="[{ required: true, message: $t('menu.form.code.required') }]"
        name="code"
      >
        <Input
          v-model:value="formState.code"
          :placeholder="$t('menu.form.code.placeholder')"
        />
      </Form.Item>

      <Form.Item
        :label="$t('menu.form.description.label')"
        name="description"
      >
        <Input.TextArea
          v-model:value="formState.description"
          :placeholder="$t('menu.form.description.placeholder')"
          :rows="4"
        />
      </Form.Item>

      <Form.Item
        v-if="showRelationType"
        :label="$t('menu.form.relation.label')"
        name="relationType"
      >
        <Radio.Group v-model:value="formState.relationType">
          <Radio value="same">{{ $t('menu.form.relation.same') }}</Radio>
          <Radio value="sub">{{ $t('menu.form.relation.sub') }}</Radio>
        </Radio.Group>
      </Form.Item>

      <Form.Item name="parentId" style="display: none">
        <Input v-model:value="formState.parentId" />
      </Form.Item>

      <Form.Item name="sort" style="display: none">
        <Input v-model:value="formState.sort" />
      </Form.Item>

      <!-- 修改角色下拉框的配置 -->
      <Form.Item
        v-if="
          formState.parentId === 0 &&
          (modalApi.getData()?.isEdit || formState.relationType === 'same')
        "
        :label="$t('menu.form.roles.label')"
        :rules="[{ required: true, message: $t('menu.form.roles.required') }]"
        name="roles"
      >
        <Select
          v-model:value="formState.roles"
          :allow-clear="false"
          :placeholder="$t('menu.form.roles.placeholder')"
          :show-search="false"
          style="width: 100%"
        >
          <Select.Option
            v-for="role in roleOptions"
            :key="role.value"
            :value="role.value"
          >
            {{ role.label }}
          </Select.Option>
        </Select>
      </Form.Item>
    </Form>
  </Modal>
</template>

<style scoped>
.icon-dropdown {
  max-height: 300px;
  padding: 8px;
  background: #fff;
}

.icon-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 4px;
  max-height: 280px;
  padding-right: 4px;
  overflow-y: auto;
}

.icon-grid::-webkit-scrollbar {
  width: 6px;
}

.icon-grid::-webkit-scrollbar-thumb {
  background-color: #d9d9d9;
  border-radius: 3px;
}

.icon-grid::-webkit-scrollbar-thumb:hover {
  background-color: #bfbfbf;
}

.icon-grid::-webkit-scrollbar-track {
  background-color: #f0f0f0;
  border-radius: 3px;
}

.icon-item {
  transition: all 0.3s;
}

.icon-item:hover {
  color: #1890ff;
  transform: scale(1.1);
}
</style>
